<!doctype html>














<!-- `site.alt_lang` can specify a language different from the UI -->
<html lang="en" 
  
>
  <!-- The Head -->

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta name="theme-color" media="(prefers-color-scheme: light)" content="#f7f7f7">
  <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1b1b1e">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
  <meta
    name="viewport"
    content="width=device-width, user-scalable=no initial-scale=1, shrink-to-fit=no, viewport-fit=cover"
  >

  

  

  
    <!-- Begin Jekyll SEO tag v2.8.0 -->
<meta name="generator" content="Jekyll v4.3.2" />
<meta property="og:title" content="Kernel Samepage Merging (KSM)" />
<meta name="author" content="Chunsheng Luo" />
<meta property="og:locale" content="en" />
<meta name="description" content="一、KSM机制" />
<meta property="og:description" content="一、KSM机制" />
<link rel="canonical" href="https://luochenglcs.github.io/posts/linux-ksm/" />
<meta property="og:url" content="https://luochenglcs.github.io/posts/linux-ksm/" />
<meta property="og:site_name" content="Cheng Luo" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2021-03-03T00:00:00+00:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="Kernel Samepage Merging (KSM)" />
<meta name="twitter:site" content="@luochenglcs" />
<meta name="twitter:creator" content="@Chunsheng Luo" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Chunsheng Luo","url":"https://github.com/luochenglcs"},"dateModified":"2023-08-04T09:06:52+00:00","datePublished":"2021-03-03T00:00:00+00:00","description":"一、KSM机制","headline":"Kernel Samepage Merging (KSM)","mainEntityOfPage":{"@type":"WebPage","@id":"https://luochenglcs.github.io/posts/linux-ksm/"},"url":"https://luochenglcs.github.io/posts/linux-ksm/"}</script>
<!-- End Jekyll SEO tag -->

  

  <title>Kernel Samepage Merging (KSM) | Cheng Luo
  </title>

  <!--
  The Favicons for Web, Android, Microsoft, and iOS (iPhone and iPad) Apps
  Generated by: https://realfavicongenerator.net/
-->



<link rel="apple-touch-icon" sizes="180x180" href="/assets/img/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/img/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/img/favicons/favicon-16x16.png">
<link rel="manifest" href="/assets/img/favicons/site.webmanifest">
<link rel="shortcut icon" href="/assets/img/favicons/favicon.ico">
<meta name="apple-mobile-web-app-title" content="Cheng Luo">
<meta name="application-name" content="Cheng Luo">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="msapplication-config" content="/assets/img/favicons/browserconfig.xml">
<meta name="theme-color" content="#ffffff">


  
    
      <link rel="preconnect" href="https://fonts.googleapis.com" >
      <link rel="dns-prefetch" href="https://fonts.googleapis.com" >
    
      <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
      <link rel="dns-prefetch" href="https://fonts.gstatic.com" crossorigin>
    
      <link rel="preconnect" href="https://fonts.googleapis.com" >
      <link rel="dns-prefetch" href="https://fonts.googleapis.com" >
    
      <link rel="preconnect" href="https://cdn.jsdelivr.net" >
      <link rel="dns-prefetch" href="https://cdn.jsdelivr.net" >
    

    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Lato&family=Source+Sans+Pro:wght@400;600;700;900&display=swap">
  

  <!-- GA -->
  

  <!-- Bootstrap -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">

  <!-- Font Awesome -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/css/all.min.css">

  <link rel="stylesheet" href="/assets/css/style.css">

  
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tocbot@4.21.0/dist/tocbot.min.css">
  

  
    <!-- Manific Popup -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/magnific-popup.min.css">
  

  <!-- JavaScript -->

  
    <!-- Switch the mode between dark and light. -->

<script type="text/javascript">
  class ModeToggle {
    static get MODE_KEY() {
      return 'mode';
    }
    static get MODE_ATTR() {
      return 'data-mode';
    }
    static get DARK_MODE() {
      return 'dark';
    }
    static get LIGHT_MODE() {
      return 'light';
    }
    static get ID() {
      return 'mode-toggle';
    }

    constructor() {
      if (this.hasMode) {
        if (this.isDarkMode) {
          if (!this.isSysDarkPrefer) {
            this.setDark();
          }
        } else {
          if (this.isSysDarkPrefer) {
            this.setLight();
          }
        }
      }

      let self = this;

      /* always follow the system prefers */
      this.sysDarkPrefers.addEventListener('change', () => {
        if (self.hasMode) {
          if (self.isDarkMode) {
            if (!self.isSysDarkPrefer) {
              self.setDark();
            }
          } else {
            if (self.isSysDarkPrefer) {
              self.setLight();
            }
          }

          self.clearMode();
        }

        self.notify();
      });
    } /* constructor() */

    get sysDarkPrefers() {
      return window.matchMedia('(prefers-color-scheme: dark)');
    }

    get isSysDarkPrefer() {
      return this.sysDarkPrefers.matches;
    }

    get isDarkMode() {
      return this.mode === ModeToggle.DARK_MODE;
    }

    get isLightMode() {
      return this.mode === ModeToggle.LIGHT_MODE;
    }

    get hasMode() {
      return this.mode != null;
    }

    get mode() {
      return sessionStorage.getItem(ModeToggle.MODE_KEY);
    }

    /* get the current mode on screen */
    get modeStatus() {
      if (this.isDarkMode || (!this.hasMode && this.isSysDarkPrefer)) {
        return ModeToggle.DARK_MODE;
      } else {
        return ModeToggle.LIGHT_MODE;
      }
    }

    setDark() {
      document.documentElement.setAttribute(ModeToggle.MODE_ATTR, ModeToggle.DARK_MODE);
      sessionStorage.setItem(ModeToggle.MODE_KEY, ModeToggle.DARK_MODE);
    }

    setLight() {
      document.documentElement.setAttribute(ModeToggle.MODE_ATTR, ModeToggle.LIGHT_MODE);
      sessionStorage.setItem(ModeToggle.MODE_KEY, ModeToggle.LIGHT_MODE);
    }

    clearMode() {
      document.documentElement.removeAttribute(ModeToggle.MODE_ATTR);
      sessionStorage.removeItem(ModeToggle.MODE_KEY);
    }

    /* Notify another plugins that the theme mode has changed */
    notify() {
      window.postMessage(
        {
          direction: ModeToggle.ID,
          message: this.modeStatus
        },
        '*'
      );
    }

    flipMode() {
      if (this.hasMode) {
        if (this.isSysDarkPrefer) {
          if (this.isLightMode) {
            this.clearMode();
          } else {
            this.setLight();
          }
        } else {
          if (this.isDarkMode) {
            this.clearMode();
          } else {
            this.setDark();
          }
        }
      } else {
        if (this.isSysDarkPrefer) {
          this.setLight();
        } else {
          this.setDark();
        }
      }

      this.notify();
    } /* flipMode() */
  } /* ModeToggle */

  const modeToggle = new ModeToggle();
</script>

  

  <!-- A placeholder to allow defining custom metadata -->

</head>


  <body>
    <!-- The Side Bar -->

<div id="sidebar" class="d-flex flex-column align-items-end">
  <div class="profile-wrapper">
    <a href="/" id="avatar" class="rounded-circle">
      
        
        <img src="/assets/img/favicons/android-chrome-512x512.png" width="112" height="112" alt="avatar" onerror="this.style.display='none'">
      
    </a>

    <div class="site-title">
      <a href="/">Cheng Luo</a>
    </div>
    <div class="site-subtitle fst-italic">Linux operating system engineer</div>
  </div>
  <!-- .profile-wrapper -->

  <ul class="nav flex-column flex-grow-1 w-100 ps-0">
    <!-- home -->
    <li class="nav-item">
      <a href="/" class="nav-link">
        <i class="fa-fw fas fa-home"></i>
        <span>HOME</span>
      </a>
    </li>
    <!-- the real tabs -->
    
      <li class="nav-item">
        <a href="/categories/" class="nav-link">
          <i class="fa-fw fas fa-stream"></i>
          

          <span>CATEGORIES</span>
        </a>
      </li>
      <!-- .nav-item -->
    
      <li class="nav-item">
        <a href="/tags/" class="nav-link">
          <i class="fa-fw fas fa-tags"></i>
          

          <span>TAGS</span>
        </a>
      </li>
      <!-- .nav-item -->
    
      <li class="nav-item">
        <a href="/archives/" class="nav-link">
          <i class="fa-fw fas fa-archive"></i>
          

          <span>ARCHIVES</span>
        </a>
      </li>
      <!-- .nav-item -->
    
      <li class="nav-item">
        <a href="/about/" class="nav-link">
          <i class="fa-fw fas fa-info-circle"></i>
          

          <span>ABOUT</span>
        </a>
      </li>
      <!-- .nav-item -->
    
  </ul>
  <!-- ul.nav.flex-column -->

  <div class="sidebar-bottom d-flex flex-wrap  align-items-center w-100">
    
      <button class="mode-toggle btn" aria-label="Switch Mode">
        <i class="fas fa-adjust"></i>
      </button>

      
        <span class="icon-border"></span>
      
    

    
      

      
        <a
          href="https://github.com/luochenglcs"
          aria-label="github"
          

          
            target="_blank"
            
          

          

          
            rel="noopener noreferrer"
          
        >
          <i class="fab fa-github"></i>
        </a>
      
    
      

      
    
      

      
        <a
          href="javascript:location.href = 'mailto:' + ['luochunsheng','ustc.edu'].join('@')"
          aria-label="email"
          

          

          

          
        >
          <i class="fas fa-envelope"></i>
        </a>
      
    
  </div>
  <!-- .sidebar-bottom -->
</div>
<!-- #sidebar -->


    <div id="main-wrapper" class="d-flex justify-content-center">
      <div id="main" class="container px-xxl-5">
        <!-- The Top Bar -->

<div id="topbar-wrapper">
  <div
    id="topbar"
    class="container d-flex align-items-center justify-content-between h-100"
  >
    <span id="breadcrumb">
      

      
        
          
            <span>
              <a href="/">
                Home
              </a>
            </span>

          
        
          
        
          
            
              <span>Kernel Samepage Merging (KSM)</span>
            

          
        
      
    </span>
    <!-- endof #breadcrumb -->

    <i id="sidebar-trigger" class="fas fa-bars fa-fw"></i>

    <div id="topbar-title">
      Post
    </div>

    <i id="search-trigger" class="fas fa-search fa-fw"></i>
    <span id="search-wrapper" class="align-items-center">
      <i class="fas fa-search fa-fw"></i>
      <input
        class="form-control"
        id="search-input"
        type="search"
        aria-label="search"
        autocomplete="off"
        placeholder="Search..."
      >
    </span>
    <span id="search-cancel">Cancel</span>
  </div>
</div>

        











<div class="row">
  <!-- core -->
  <div id="core-wrapper" class="col-12 col-lg-11 col-xl-9 pe-xl-4">
    

    <div class="post px-1 px-md-2">
      

      
        
      
        <!-- Refactor the HTML structure -->



<!--
  In order to allow a wide table to scroll horizontally,
  we suround the markdown table with `<div class="table-wrapper">` and `</div>`
-->



<!--
  Fixed kramdown code highlight rendering:
  https://github.com/penibelst/jekyll-compress-html/issues/101
  https://github.com/penibelst/jekyll-compress-html/issues/71#issuecomment-188144901
-->



<!-- Change the icon of checkbox -->


<!-- images -->



  
  

  <!-- CDN URL -->
  

  <!-- Add image path -->
  

  
    
      
      
    

    
    

    

    
    

    
    
    
    

    
      

      
      
      

      
    
      

      
      
      

      
    
      

      
      
      

      
    

    <!-- take out classes -->
    

    

    

    

    <!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
    
    

    <!-- add image placeholder -->
    
      
    

    <!-- Bypass the HTML-proofer test -->
    

    
      <!-- make sure the `<img>` is wrapped by `<a>` -->
      

      
        <!-- create the image wrapper -->
        
      
    

    <!-- combine -->
    

  
    

    
    

    

    
    

    
    
    
    

    
      

      
      
      

      
    
      

      
      
      

      
    
      

      
      
      

      
    

    <!-- take out classes -->
    

    

    

    

    <!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
    
    

    <!-- add image placeholder -->
    
      
    

    <!-- Bypass the HTML-proofer test -->
    

    
      <!-- make sure the `<img>` is wrapped by `<a>` -->
      

      
        <!-- create the image wrapper -->
        
      
    

    <!-- combine -->
    

  
    

    
    

    

    
    

    
    
    
    

    
      

      
      
      

      
    
      

      
      
      

      
    
      

      
      
      

      
    

    <!-- take out classes -->
    

    

    

    

    <!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
    
    

    <!-- add image placeholder -->
    
      
    

    <!-- Bypass the HTML-proofer test -->
    

    
      <!-- make sure the `<img>` is wrapped by `<a>` -->
      

      
        <!-- create the image wrapper -->
        
      
    

    <!-- combine -->
    

  
    

    
    

    

    
    

    
    
    
    

    
      

      
      
      

      
    
      

      
      
      

      
    
      

      
      
      

      
    

    <!-- take out classes -->
    

    

    

    

    <!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
    
    

    <!-- add image placeholder -->
    
      
    

    <!-- Bypass the HTML-proofer test -->
    

    
      <!-- make sure the `<img>` is wrapped by `<a>` -->
      

      
        <!-- create the image wrapper -->
        
      
    

    <!-- combine -->
    

  
    

    
    

    

    
    

    
    
    
    

    
      

      
      
      

      
    
      

      
      
      

      
    
      

      
      
      

      
    

    <!-- take out classes -->
    

    

    

    

    <!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
    
    

    <!-- add image placeholder -->
    
      
    

    <!-- Bypass the HTML-proofer test -->
    

    
      <!-- make sure the `<img>` is wrapped by `<a>` -->
      

      
        <!-- create the image wrapper -->
        
      
    

    <!-- combine -->
    

  
    

    
    

    

    
    

    
    
    
    

    
      

      
      
      

      
    
      

      
      
      

      
    
      

      
      
      

      
    

    <!-- take out classes -->
    

    

    

    

    <!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
    
    

    <!-- add image placeholder -->
    
      
    

    <!-- Bypass the HTML-proofer test -->
    

    
      <!-- make sure the `<img>` is wrapped by `<a>` -->
      

      
        <!-- create the image wrapper -->
        
      
    

    <!-- combine -->
    

  
    

    
    

    

    
    

    
    
    
    

    
      

      
      
      

      
    
      

      
      
      

      
    
      

      
      
      

      
    

    <!-- take out classes -->
    

    

    

    

    <!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
    
    

    <!-- add image placeholder -->
    
      
    

    <!-- Bypass the HTML-proofer test -->
    

    
      <!-- make sure the `<img>` is wrapped by `<a>` -->
      

      
        <!-- create the image wrapper -->
        
      
    

    <!-- combine -->
    

  
    

    
    

    

    
    

    
    
    
    

    
      

      
      
      

      
    
      

      
      
      

      
    
      

      
      
      

      
    

    <!-- take out classes -->
    

    

    

    

    <!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
    
    

    <!-- add image placeholder -->
    
      
    

    <!-- Bypass the HTML-proofer test -->
    

    
      <!-- make sure the `<img>` is wrapped by `<a>` -->
      

      
        <!-- create the image wrapper -->
        
      
    

    <!-- combine -->
    

  

  



<!-- Add header for code snippets -->



<!-- Create heading anchors -->





  
  

  

  
  

  
    
    

    
      
        
        
      

      
      

      
      
      

      

    
      

      
      

      
      
      

      

    

    

  

  
  

  
    
    

    
      
        
        
      

      
      

      
      
      

      

    
      

      
      

      
      
      

      

    
      

      
      

      
      
      

      

    

    

  

  
  

  
    
    

    
      
        
        
      

      
      

      
      
      

      

    
      

      
      

      
      
      

      

    
      

      
      

      
      
      

      

    
      

      
      

      
      
      

      

    

    

  




<!-- return -->




<h1 data-toc-skip>Kernel Samepage Merging (KSM)</h1>

<div class="post-meta text-muted">
    <!-- published date -->
    <span>
      Posted
      <!--
  Date format snippet
  See: ${JS_ROOT}/utils/locale-dateime.js
-->





<em
  class=""
  data-ts="1614729600"
  data-df="ll"
  
    data-bs-toggle="tooltip" data-bs-placement="bottom"
  
>
  Mar  3, 2021
</em>

    </span>

    <!-- lastmod date -->
    
    <span>
      Updated
      <!--
  Date format snippet
  See: ${JS_ROOT}/utils/locale-dateime.js
-->





<em
  class=""
  data-ts="1691140012"
  data-df="ll"
  
    data-bs-toggle="tooltip" data-bs-placement="bottom"
  
>
  Aug  4, 2023
</em>

    </span>
    

  

  <div class="d-flex justify-content-between">
    <!-- author(s) -->
    <span>
      

      By

      <em>
      
        
          <a href="https://github.com/luochenglcs">Chunsheng Luo</a>
          
        
      
      </em>
    </span>

    <div>
      <!-- read time -->
      <!-- Calculate the post's reading time, and display the word count in tooltip -->



<!-- words per minute -->










<!-- return element -->
<span
  class="readtime"
  data-bs-toggle="tooltip"
  data-bs-placement="bottom"
  title="2719 words"
>
  <em>15 min</em> read</span>

    </div>

  </div> <!-- .d-flex -->

</div> <!-- .post-meta -->
<div class="post-content">
  <h3 id="一ksm机制"><span class="me-2">一、KSM机制</span><a href="#一ksm机制" class="anchor text-muted"><i class="fas fa-hashtag"></i></a></h3>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre><span class="nl">https:</span><span class="c1">//zhuanlan.zhihu.com/p/102469328</span>
<span class="err">详细的代码流程图</span>
<span class="n">https</span><span class="o">:</span><span class="c1">//www.kernelnote.com/entry/linux-ksm-merge</span>
<span class="err">详细的代码分析</span>
</pre></td></tr></tbody></table></code></div></div>

<p>​	内核采用虚拟内存管理技术为每个进程分配独立的虚拟内存地址空间。而物理内存的分配是由进程去访问虚拟地址时产生缺页异常 (Page Fault) 来
触发。一个进程的虚拟地址空间在内核中用内存描述符<code class="language-plaintext highlighter-rouge">struct mm_struct</code>进行表示，而进程的虚拟地址空间又被划分为多个虚拟内存区域<code class="language-plaintext highlighter-rouge">struct vm_area_struct</code>，简称<code class="language-plaintext highlighter-rouge">vma</code>。另外，进程描述符由<code class="language-plaintext highlighter-rouge">struct task_struct</code>中的<code class="language-plaintext highlighter-rouge">mm</code>域记录。</p>

<p><a href="/posts/.\images\linux-ksm\进程vma+pgd page table.png" class="popup img-link "><img data-src="/posts/.\images\linux-ksm\进程vma+pgd page table.png" div="" align="left" class="lazyload" data-proofer-ignore></a></p>

<p><code class="language-plaintext highlighter-rouge">KSM</code>后常驻一个名叫<code class="language-plaintext highlighter-rouge">ksmd</code>非实时线程。它会执行 ksm.c 源码里的<code class="language-plaintext highlighter-rouge">ksm_do_scan</code>接口定时扫描被标记为<code class="language-plaintext highlighter-rouge">MMF_VM_MERGEABLE</code>的<code class="language-plaintext highlighter-rouge">mm_struct</code>[内
存描述符]，调用<code class="language-plaintext highlighter-rouge">cmp_and_merge_page</code>识别并合并内容完全一样的物理页，扫描的间隔和每次扫描的页数分别由<code class="language-plaintext highlighter-rouge">/sys/kernel/mm/ksm/
pages_to_scan</code>、<code class="language-plaintext highlighter-rouge">/sys/kernel/mm/ksm/sleep_millisecs</code>控制。用户层可以通过系统调用<code class="language-plaintext highlighter-rouge">madvise(addr,length,MADV_MERGEABLE)</code>对一块页
对齐的内存标记为可用于 KSM 合并。此外由于<code class="language-plaintext highlighter-rouge">madvise</code>系统调用会通过内核源码 madvise.c 里的<code class="language-plaintext highlighter-rouge">madvise_behavior</code>接口对内存区域 vma 中的
内存进行标记，如果该区间和周围的内存区间标记不同，那么会分配新的<code class="language-plaintext highlighter-rouge">vma</code>，而内核对进程持有的<code class="language-plaintext highlighter-rouge">vma</code>是有限制的，分配的 vma 数目必须小于<code class="language-plaintext highlighter-rouge">/
proc/sys/vm/max_map_count</code>里的限制，一旦超出，那么会引发<code class="language-plaintext highlighter-rouge">OOM Killer</code>导致进程<code class="language-plaintext highlighter-rouge">crash</code>。<strong>如果调大<code class="language-plaintext highlighter-rouge">max_map_count</code>产生过多的<code class="language-plaintext highlighter-rouge">vma</code>会
导致系统的性能下降，我们应该根据自身业务的规模进行合理调整，同时有必要加上监控预警。</strong></p>

<p><a href="/posts/.\images\linux-ksm\ksm-function-flow.png" class="popup img-link "><img data-src="/posts/.\images\linux-ksm\ksm-function-flow.png" div="" align="left" class="lazyload" data-proofer-ignore></a></p>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nl">https:</span><span class="c1">//maggie262.github.io/2020/11/20/ksm/</span>
</pre></td></tr></tbody></table></code></div></div>

<p>KSM数据结构关系图：</p>

<p><a href="/posts/.\images\linux-ksm\ksm.svg" class="popup img-link "><img data-src="/posts/.\images\linux-ksm\ksm.svg" div="" align="left" class="lazyload" data-proofer-ignore></a></p>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="rouge-code"><pre><span class="nl">https:</span><span class="c1">//www.cnblogs.com/arnoldlu/p/8335541.html</span>
<span class="n">ksm_do_scan</span>
    <span class="n">scan_get_next_rmap_item</span><span class="o">---------------------</span><span class="err">选取合适的匿名页面</span>
    <span class="n">cmp_and_merge_page</span><span class="o">--------------------------</span><span class="err">将页面与</span><span class="n">root_stable_tree</span><span class="o">/</span><span class="n">root_unstable_tree</span><span class="err">中页面进行比较，判断是否能合并</span>
        <span class="n">stable_tree_search</span><span class="o">----------------------</span><span class="err">搜索</span><span class="n">stable</span><span class="err">红黑树并查找是否有和</span><span class="n">page</span><span class="err">内容一致的节点</span>
        <span class="n">try_to_merge_with_ksm_page</span><span class="o">--------------</span><span class="err">尝试将候选页合并到</span><span class="n">KSM</span><span class="err">页面中</span>
        <span class="n">stable_tree_append</span>
        <span class="n">unstable_tree_search_insert</span><span class="o">-------------</span><span class="err">搜索</span><span class="n">unstable</span><span class="err">红黑树中是否有和该页内容相同的节点</span>
        <span class="n">try_to_merge_two_pages</span><span class="o">------------------</span><span class="err">若在</span><span class="n">unstable</span><span class="err">红黑树中找到和当前页内容相同节点，尝试合并这两页面成为一个</span><span class="n">KSM</span><span class="err">页面</span>
        <span class="n">stable_tree_append</span><span class="o">----------------------</span><span class="err">将合并的两个页面对应</span><span class="n">rmap_item</span><span class="err">添加到</span><span class="n">stable</span><span class="err">节点哈希表中</span>
        <span class="n">break_cow</span>
    
<span class="n">KSM</span><span class="err">页面和匿名页面的区别</span>
<span class="err">分两种情况，匿名页是父子进程</span><span class="n">VMA</span><span class="err">共享同一个匿名页面；</span><span class="n">ksm</span><span class="err">是不相干的进程</span><span class="n">VMA</span><span class="err">共享同一个匿名页面。</span>
</pre></td></tr></tbody></table></code></div></div>

<h3 id="二反向映射"><span class="me-2">二、反向映射</span><a href="#二反向映射" class="anchor text-muted"><i class="fas fa-hashtag"></i></a></h3>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nl">https:</span><span class="c1">//os.51cto.com/art/202011/632380.htm</span>
</pre></td></tr></tbody></table></code></div></div>

<p><strong>目的</strong>：为了找到一个物理页面对应的页表项.</p>

<p><strong>用途</strong>：内存回收，内存碎片整理，CMA, 巨型页，页迁移等各个场景中都能发现反向映射所做的关键性的工作。</p>

<h4 id="1-反向映射发展"><span class="me-2">1 反向映射发展</span><a href="#1-反向映射发展" class="anchor text-muted"><i class="fas fa-hashtag"></i></a></h4>

<h4 id="2反向映射分类据结构"><span class="me-2">2.反向映射分类据结构</span><a href="#2反向映射分类据结构" class="anchor text-muted"><i class="fas fa-hashtag"></i></a></h4>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="rouge-code"><pre><span class="mi">1</span><span class="err">、</span><span class="n">fork</span><span class="err">流程中会存在反向映射的建立，可以熟悉建立流程</span>
<span class="n">SYSCALL_DEFINE0</span><span class="p">(</span><span class="n">fork</span><span class="p">)</span>
<span class="n">kernel_clone</span>
<span class="n">copy_process</span>
<span class="n">copy_mm</span>
<span class="n">dump_mm</span>
<span class="n">dup_mmap</span>
	<span class="o">-&gt;|</span><span class="n">anon_vma_fork</span> <span class="err">匿名映射反向映射创建</span>
	<span class="o">-&gt;|</span><span class="n">vma_interval_tree_insert_after</span>	<span class="err">文件映射反向映射创建</span>
<span class="mi">2</span><span class="err">、内存回收或者页表迁移，会通过反向映射查找对应的</span><span class="n">pte</span><span class="err">，可以熟悉查找流程</span><span class="p">.</span>
    <span class="n">try_to_unmap</span>
    <span class="o">-&gt;|</span><span class="n">rmap_walk</span>
    	<span class="o">-&gt;|</span><span class="n">rmap_walk_ksm</span> <span class="k">if</span> <span class="n">PageKsm</span><span class="p">(</span><span class="n">page</span><span class="p">)</span>  <span class="n">ksm</span><span class="err">页</span>
    	<span class="o">-&gt;|</span><span class="n">rmap_walk_anon</span> <span class="k">if</span> <span class="n">PageAnon</span><span class="p">(</span><span class="n">page</span><span class="p">)</span> <span class="err">匿名页</span>
    	<span class="o">-&gt;|</span><span class="n">rmap_walk_file</span> <span class="n">page</span> <span class="n">cache</span><span class="err">页</span>
</pre></td></tr></tbody></table></code></div></div>

<h5 id="1匿名反向映射"><span class="me-2">(1)匿名反向映射</span><a href="#1匿名反向映射" class="anchor text-muted"><i class="fas fa-hashtag"></i></a></h5>

<p>​	匿名页的共享主要发生在父进程fork子进程的时候，父fork子进程时，会复制所有vma给子进程，并通过调用dup_mmap-&gt;anon_vma_fork
建立子进程的rmap以及和长辈进程rmap关系结构：</p>

<p>主要通过anon_vma这个数据结构体中的红黑树将共享父进程的页的所有子进程的vma联系起来(通过anon_vma_chain 来联系对应的vma和av)，
当然这个关系建立比较复杂，涉及到vma,avc和av这些数据结构体。</p>

<p>而在缺页异常do_anonymous_page的时候将page和vma相关联</p>

<p><a href="/posts/.\images\linux-ksm\匿名映射的反向映射.jpg" class="popup img-link "><img data-src="/posts/.\images\linux-ksm\匿名映射的反向映射.jpg" div="" align="left" class="lazyload" data-proofer-ignore></a></p>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="n">try_to_unmap</span> <span class="c1">//mm/rmap.c </span>
<span class="o">-&gt;</span><span class="n">rmap_walk</span> 
  <span class="o">-&gt;</span><span class="n">rmap_walk_anon</span> 
     <span class="o">-&gt;</span><span class="n">anon_vma_interval_tree_foreach</span><span class="p">(</span><span class="n">avc</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">anon_vma</span><span class="o">-&gt;</span><span class="n">rb_root</span><span class="p">,</span><span class="n">pgoff_start</span><span class="p">,</span> <span class="n">pgoff_end</span><span class="p">)</span> 
         <span class="o">-&gt;</span><span class="n">rwc</span><span class="o">-&gt;</span><span class="n">rmap_one</span> 
            <span class="o">-&gt;</span><span class="n">try_to_unmap_one</span> 
</pre></td></tr></tbody></table></code></div></div>

<p>对于候选页，会拿到候选页相关联的anon_vma，然后从anon_vma的红黑树中遍历到所有共享这个页的vma，然后对于每一个vma通过
try_to_unmap_one来处理相对应的页表项，将映射关系解除。</p>

<h5 id="2文件反向映射"><span class="me-2">(2)文件反向映射</span><a href="#2文件反向映射" class="anchor text-muted"><i class="fas fa-hashtag"></i></a></h5>

<p>​	文件页的共享主要发生在多个进程共享libc库，同一个库文件可以只需要读取到page cache一次，然后通过各个进程的页表映射到各个进程的vma
中。管理共享文件页的所以vma是通过address_space的区间树来管理，在mmap或者fork的时候将vma加入到这颗区间树中：</p>

<p>发生文件映射缺页异常的时候，将page和address_space相关联。</p>

<p><a href="/posts/.\images\linux-ksm\文件映射的反向映射.jpg" class="popup img-link "><img data-src="/posts/.\images\linux-ksm\文件映射的反向映射.jpg" div="" align="left" class="lazyload" data-proofer-ignore></a></p>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre><span class="n">try_to_unmap</span> <span class="c1">//mm/rmap.c </span>
<span class="o">-&gt;</span><span class="n">rmap_walk</span> 
  <span class="o">-&gt;</span><span class="n">rmap_walk_file</span> 
    <span class="o">-&gt;</span><span class="n">vma_interval_tree_foreach</span><span class="p">(</span><span class="n">vma</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">mapping</span><span class="o">&gt;</span><span class="n">i_mmap</span><span class="p">,</span><span class="n">pgoff_start</span><span class="p">,</span> <span class="n">pgoff_end</span><span class="p">)</span>  
         <span class="o">-&gt;</span><span class="n">rwc</span><span class="o">-&gt;</span><span class="n">rmap_one</span>
</pre></td></tr></tbody></table></code></div></div>

<p>对于每一个候选的文件页，如果是映射页，就会遍历page所对应的address_space的区间树，对于每一个满足条件的vma，
调用try_to_unmap_one来找到pte并解除映射关系。</p>

<h5 id="3ksm反向映射"><span class="me-2">(3)KSM反向映射</span><a href="#3ksm反向映射" class="anchor text-muted"><i class="fas fa-hashtag"></i></a></h5>

<p>​		遍历ksm机制中两课红黑树，一棵是stable tree,一棵是unstable tree， 然后通过匿名映射的反向映射查找对应的vma。</p>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
</pre></td><td class="rouge-code"><pre><span class="n">try_to_unmap</span> <span class="c1">//mm/rmap.c </span>
<span class="o">-&gt;</span><span class="n">rmap_walk</span> 
   <span class="o">-&gt;</span><span class="n">rmap_walk_ksm</span>  <span class="c1">//mm/ksm.c </span>
        <span class="o">-&gt;</span> <span class="n">hlist_for_each_entry</span><span class="p">(</span><span class="n">rmap_item</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">stable_node</span><span class="o">-&gt;</span><span class="n">hlist</span><span class="p">,</span> <span class="n">hlist</span><span class="p">)</span> 
    <span class="o">-&gt;</span><span class="n">anon_vma_interval_tree_foreach</span><span class="p">(</span><span class="n">vmac</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">anon_vma</span><span class="o">-&gt;</span><span class="n">rb_root</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="n">ULONG_MAX</span><span class="p">)</span>  
      <span class="o">-&gt;</span><span class="n">rwc</span><span class="o">-&gt;</span><span class="n">rmap_one</span> 
</pre></td></tr></tbody></table></code></div></div>

<h4 id="3总结"><span class="me-2">3.总结</span><a href="#3总结" class="anchor text-muted"><i class="fas fa-hashtag"></i></a></h4>

<p>匿名页，文件页和ksm页的反向映射,分别通过page所对应的的vma, address_space, stable_node结构来查找vma</p>

<h5 id="三额外知识"><span class="me-2">三、额外知识：</span><a href="#三额外知识" class="anchor text-muted"><i class="fas fa-hashtag"></i></a></h5>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
</pre></td><td class="rouge-code"><pre><span class="nl">https:</span><span class="c1">//blog.csdn.net/Z_Stand/article/details/102222612 </span>
<span class="err">文件</span><span class="n">IO</span><span class="err">与内存映射：</span><span class="n">page</span> <span class="n">cache</span><span class="err">页高速缓存</span>
</pre></td></tr></tbody></table></code></div></div>

<h6 id="i-page-cache-level0视图">i page cache level0视图</h6>

<p><a href="/posts/.\images\linux-ksm\page-cache-level0.png" class="popup img-link "><img data-src="/posts/.\images\linux-ksm\page-cache-level0.png" div="" align="left" class="lazyload" data-proofer-ignore></a></p>

<h6 id="ii-page-cache作用">ii. page cache作用</h6>

<p>​	提高文件系统性能，内核利用一部分物理内存分配出缓冲区，用于缓存系统操作和数据文件，当内核收到读写的请求时，内核先去缓存区找是否有请
求的数据，有就直接返回，如果没有则通过驱动程序直接操作磁盘。</p>

<p>​	缓存机制优点：减少系统调用次数，降低CPU上下文切换和磁盘访问频率。</p>

<p><a href="/posts/.\images\linux-ksm\page-cahce缓存作用.png" class="popup img-link "><img data-src="/posts/.\images\linux-ksm\page-cahce缓存作用.png" div="" align="left" class="lazyload" data-proofer-ignore></a></p>

<h6 id="iii-文件读写">iii. 文件读写</h6>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="rouge-code"><pre><span class="err">读文件流程如下</span>
<span class="err">数据结构关联</span><span class="o">:</span><span class="n">inode</span> <span class="o">-&gt;</span> <span class="n">i_mapping</span> <span class="err">指向</span><span class="n">address_space</span><span class="err">对象</span><span class="p">,</span><span class="n">address_space</span><span class="o">-&gt;</span><span class="n">host</span><span class="err">指向</span><span class="n">inode</span>
<span class="err">数据结构关联</span><span class="o">:</span><span class="n">page</span><span class="o">-&gt;</span><span class="n">mapping</span> <span class="err">指向页缓存</span><span class="n">owner</span><span class="err">的</span><span class="n">address_space</span>
<span class="err">系统调用传参</span><span class="o">:</span><span class="err">文件描述符</span><span class="o">+</span><span class="err">文件偏移地址</span>
<span class="err">操作系统找到文件</span><span class="n">address_space</span><span class="err">，根据偏移量到页缓存中查找</span><span class="n">page</span>
<span class="err">若查找到，返回数据到用户空间</span>
<span class="err">否则，内核新建一个</span><span class="n">page</span><span class="err">并加入到页缓存，数据从磁盘载入该项</span>
<span class="err">调用</span><span class="n">readpage</span><span class="err">方法将数据返回给用户空间</span>
    
<span class="err">写文件流程如下：</span>
<span class="err">数据结构关联</span><span class="o">:</span><span class="n">inode</span> <span class="o">-&gt;</span> <span class="n">i_mapping</span> <span class="err">指向</span><span class="n">address_space</span><span class="err">对象</span><span class="p">,</span><span class="n">address_space</span><span class="o">-&gt;</span><span class="n">host</span><span class="err">指向</span><span class="n">inode</span>
<span class="err">数据结构关联</span><span class="o">:</span><span class="n">page</span><span class="o">-&gt;</span><span class="n">mapping</span> <span class="err">指向页缓存</span><span class="n">owner</span><span class="err">的</span><span class="n">address_space</span>
<span class="err">系统调用传参</span><span class="o">:</span><span class="err">文件描述符</span><span class="o">+</span><span class="err">文件偏移地址</span>
<span class="err">操作系统找到文件</span><span class="n">address_space</span><span class="err">，根据偏移量到页缓存中查找</span><span class="n">page</span>
<span class="err">若查找到，将数据写入到该缓存中，该页成为脏页</span>
<span class="err">若没有查找到，向缓存的计数树管理的页面中添加一个新的页面，并将用户空间的数据写入到该页面</span>
<span class="err">当数据满足页缓存的时间或空间原理时，使用</span><span class="n">pdflush</span><span class="err">后台回写例程来将脏页数据会写到磁盘</span>

</pre></td></tr></tbody></table></code></div></div>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="nl">https:</span><span class="c1">//xgwang0.github.io/2018/12/24/Linux-FileSystem_File-Read_Write-Process/</span>
<span class="n">https</span><span class="o">:</span><span class="c1">//blog.csdn.net/Frecon/article/details/80153535?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169106404316800182147077%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&amp;request_id=169106404316800182147077&amp;biz_id=0&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-80153535-null-null.268^v1^koosearch&amp;utm_term=%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F&amp;spm=1018.2226.3001.4450</span>
<span class="err">文件读写</span>
</pre></td></tr></tbody></table></code></div></div>

<p><a href="/posts/.\images\linux-ksm\file_sys_structure.png" class="popup img-link "><img data-src="/posts/.\images\linux-ksm\file_sys_structure.png" div="" align="left" class="lazyload" data-proofer-ignore></a></p>

<h6 id="iv-page-cache控制">iv. page cache控制</h6>

<p>​	sysctl 参数： dirty_ratio<code class="language-plaintext highlighter-rouge">和</code>dirty_background_ratio</p>

<h6 id="v-文件读写-与-文件映射">v. 文件读写 与 文件映射</h6>

<div class="language-c highlighter-rouge"><div class="code-header">
        <span data-label-text="C"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nl">https:</span><span class="c1">//www.cnblogs.com/charlesblc/p/6263665.html</span>
</pre></td></tr></tbody></table></code></div></div>

<p>而使用mmap操作文件中，创建新的虚拟内存区域和建立文件磁盘地址和虚拟内存区域映射这两步，没有任何文件拷贝操作。而之后访
问数据时发现内存中并无数据而发起的缺页异常过程，可以通过已经建立好的映射关系，只使用一次数据拷贝，就从磁盘中将数据传
入内存的用户空间中，供进程使用。</p>

<p><strong>总而言之，常规文件操作需要从磁盘到页缓存再到用户主存的两次数据拷贝。而mmap操控文件，只需要从磁盘到用</strong>
<strong>户主存的一次数据拷贝过程。</strong>说白了，mmap的关键点是实现了用户空间和内核空间的数据直接交互而省去了空间不同**
<strong>数据不通的繁琐过程。因此mmap效率更高。</strong></p>

<div class="language-plaintext highlighter-rouge"><div class="code-header">
        <span data-label-text="Plaintext"><i class="fas fa-code fa-fw small"></i></span>
      <button aria-label="copy" data-title-succeed="Copied!"><i class="far fa-clipboard"></i></button></div><div class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="rouge-code"><pre>mmap优点总结
由上文讨论可知，mmap优点共有一下几点：
1、对文件的读取操作跨过了页缓存，减少了数据的拷贝次数，用内存读写取代I/O读写，提高了文件读取效率。
2、实现了用户空间和内核空间的高效交互方式。两空间的各自修改操作可以直接反映在映射的区域内，从而被
对方空间及时捕捉。
3、提供进程间共享内存及相互通信的方式。不管是父子进程还是无亲缘关系的进程，都可以将自身用户空间映射
到同一个文件或匿名映射到同一片区域。从而通过各自对映射区域的改动，达到进程间通信和进程间共享的目的。
     同时，如果进程A和进程B都映射了区域C，当A第一次读取C时通过缺页从磁盘复制文件页到内存中；但当B
     再读C的相同页面时，虽然也会产生缺页异常，但是不再需要从磁盘中复制文件过来，而可直接使用已经保
     存在内存中的文件数据。
4、可用于实现高效的大规模数据传输。内存空间不足，是制约大数据操作的一个方面，解决方案往往是借助硬盘
空间协助操作，补充内存的不足。但是进一步会造成大量的文件I/O操作，极大影响效率。这个问题可以通过mmap映射
很好的解决。换句话说，但凡是需要用磁盘空间代替内存的时候，mmap都可以发挥其功效。
</pre></td></tr></tbody></table></code></div></div>

</div>

<div class="post-tail-wrapper text-muted">

  <!-- categories -->
  
  <div class="post-meta mb-3">
    <i class="far fa-folder-open fa-fw me-1"></i>
    
      <a href='/categories/linux/'>linux</a>,
      <a href='/categories/ksm/'>KSM</a>
  </div>
  
  <!-- post.html -->

  <!-- tags -->
  
  <div class="post-tags">
    <i class="fa fa-tags fa-fw me-1"></i>
      
      <a href="/tags/ksm/"
          class="post-tag no-text-decoration" >KSM</a>
      
  </div>
  
  
  <div class="post-tail-bottom
    d-flex justify-content-between align-items-center mt-3 pt-5 pb-2">
    <div class="license-wrapper">

      

        

        This post is licensed under 
        <a href="https://creativecommons.org/licenses/by/4.0/">
          CC BY 4.0
        </a>
         by the author.

      
    </div>

    <!-- Post sharing snippet -->

<div class="share-wrapper">
  <span class="share-label text-muted me-1">Share</span>
  <span class="share-icons">
    
    
    

    
      
      <a
        href="https://twitter.com/intent/tweet?text=Kernel%20Samepage%20Merging%20(KSM)%20-%20Cheng%20Luo&url=https%3A%2F%2Fluochenglcs.github.io%2Fposts%2Flinux-ksm%2F"
        data-bs-toggle="tooltip"
        data-bs-placement="top"
        title="Twitter"
        target="_blank"
        rel="noopener"
        aria-label="Twitter"
      >
        <i class="fa-fw fab fa-twitter"></i>
      </a>
    
      
      <a
        href="https://www.facebook.com/sharer/sharer.php?title=Kernel%20Samepage%20Merging%20(KSM)%20-%20Cheng%20Luo&u=https%3A%2F%2Fluochenglcs.github.io%2Fposts%2Flinux-ksm%2F"
        data-bs-toggle="tooltip"
        data-bs-placement="top"
        title="Facebook"
        target="_blank"
        rel="noopener"
        aria-label="Facebook"
      >
        <i class="fa-fw fab fa-facebook-square"></i>
      </a>
    
      
      <a
        href="https://t.me/share/url?url=https%3A%2F%2Fluochenglcs.github.io%2Fposts%2Flinux-ksm%2F&text=Kernel%20Samepage%20Merging%20(KSM)%20-%20Cheng%20Luo"
        data-bs-toggle="tooltip"
        data-bs-placement="top"
        title="Telegram"
        target="_blank"
        rel="noopener"
        aria-label="Telegram"
      >
        <i class="fa-fw fab fa-telegram"></i>
      </a>
    

    <i
      id="copy-link"
      class="fa-fw fas fa-link small"
      data-bs-toggle="tooltip"
      data-bs-placement="top"
      title="Copy link"
      data-title-succeed="Link copied successfully!"
    >
    </i>
  </span>
</div>


  </div><!-- .post-tail-bottom -->

</div><!-- div.post-tail-wrapper -->


      
    
      
    </div>
  </div>
  <!-- #core-wrapper -->

  <!-- panel -->
  <div id="panel-wrapper" class="col-xl-3 ps-2 text-muted">
    <div class="access">
      <!-- Get the last 5 posts from lastmod list. -->














  <div id="access-lastmod" class="post">
    <div class="panel-heading">Recently Updated</div>
    <ul class="post-content list-unstyled ps-0 pb-1 ms-1 mt-2">
      
        
        
        
        <li class="text-truncate lh-lg">
          <a href="/posts/%E5%86%85%E5%AD%98%E6%95%B0%E6%8D%AE%E5%BA%93/">MMDB (memory database)</a>
        </li>
      
        
        
        
        <li class="text-truncate lh-lg">
          <a href="/posts/userspace-rcu%E9%94%81/">userspace rcu lock</a>
        </li>
      
        
        
        
        <li class="text-truncate lh-lg">
          <a href="/posts/Real-time-operating-system/">Realtime Operating System</a>
        </li>
      
        
        
        
        <li class="text-truncate lh-lg">
          <a href="/posts/HUNDSUN-LightOS/">Hundsun Lightos</a>
        </li>
      
        
        
        
        <li class="text-truncate lh-lg">
          <a href="/posts/linux-struct-folio/">struct folio</a>
        </li>
      
    </ul>
  </div>
  <!-- #access-lastmod -->


      <!-- The trending tags list -->















  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
      
        
        

  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
      
        
        

  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
      
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        



  <div id="access-tags">
    <div class="panel-heading">Trending Tags</div>
    <div class="d-flex flex-wrap mt-3 mb-1 me-3">
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/lock/">lock</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/libumem/">libumem</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/mm/">mm</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/autonuma/">autonuma</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/bfs/">BFS</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/bus/">Bus</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/caladan/">caladan</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/damon/">damon</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/deep-learning/">Deep Learning</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/dma/">DMA</a>
      
    </div>
  </div>


    </div>

    
      
      



  <div id="toc-wrapper" class="ps-0 pe-4 mb-5">
    <div class="panel-heading ps-3 pt-2 mb-2">Contents</div>
    <nav id="toc"><ul><li>Kernel Samepage Merging (KSM)<ul><li><a href="#一ksm机制">一、KSM机制</a></li><li><a href="#二反向映射">二、反向映射</a><ul><li><a href="#1-反向映射发展">1 反向映射发展</a></li><li><a href="#2反向映射分类据结构">2.反向映射分类据结构</a><ul><li><a href="#1匿名反向映射">(1)匿名反向映射</a></li><li><a href="#2文件反向映射">(2)文件反向映射</a></li><li><a href="#3ksm反向映射">(3)KSM反向映射</a></li></ul></li><li><a href="#3总结">3.总结</a><ul><li><a href="#三额外知识">三、额外知识：</a><ul><li><a href="#i-page-cache-level0视图">i page cache level0视图</a></li><li><a href="#ii-page-cache作用">ii. page cache作用</a></li><li><a href="#iii-文件读写">iii. 文件读写</a></li><li><a href="#iv-page-cache控制">iv. page cache控制</a></li><li><a href="#v-文件读写-与-文件映射">v. 文件读写 与 文件映射</a></li></ul></li></ul></li></ul></li></ul></li></ul></li></ul></nav>
  </div>
  


    
  </div>
</div>

<!-- tail -->

  <div class="row">
    <div id="tail-wrapper" class="col-12 col-lg-11 col-xl-9 px-3 pe-xl-4 mt-5">
      
        
        <!--
  Recommend the other 3 posts according to the tags and categories of the current post,
  if the number is not enough, use the other latest posts to supplement.
-->

<!-- The total size of related posts -->


<!-- An random integer that bigger than 0 -->


<!-- Equals to TAG_SCORE / {max_categories_hierarchy} -->








  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  
    
  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  






<!-- Fill with the other newlest posts -->





  <div id="related-posts" class="mb-2 mb-sm-4">
    <h3 class="pt-2 mb-4 ms-1" data-toc-skip>
      Further Reading
    </h3>
    <div class="row row-cols-1 row-cols-md-2 row-cols-xl-3 g-4 mb-4">
      
        
        
        <div class="col">
          <a href="/posts/linux-kcsan/" class="card post-preview h-100">
            <div class="card-body">
              <!--
  Date format snippet
  See: ${JS_ROOT}/utils/locale-dateime.js
-->





<em
  class="small"
  data-ts="1599782400"
  data-df="ll"
  
>
  Sep 11, 2020
</em>

              <h4 class="pt-0 my-2" data-toc-skip>The Kernel Concurrency Sanitizer (KCSAN)</h4>
              <div class="text-muted small">
                <p>
                  





                  1 kcasan

2 使用

                </p>
              </div>
            </div>
          </a>
        </div>
      
        
        
        <div class="col">
          <a href="/posts/linux-kprobe/" class="card post-preview h-100">
            <div class="card-body">
              <!--
  Date format snippet
  See: ${JS_ROOT}/utils/locale-dateime.js
-->





<em
  class="small"
  data-ts="1600041600"
  data-df="ll"
  
>
  Sep 14, 2020
</em>

              <h4 class="pt-0 my-2" data-toc-skip>Kernel Probe (kprobe)</h4>
              <div class="text-muted small">
                <p>
                  





                  1 kprobe

2 debugfs kprobe trace
kprobe trace 使用debugfs的trace功能
 p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS]  : Set a probe
 r[MAXACTIVE][:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS]  : Set a r...
                </p>
              </div>
            </div>
          </a>
        </div>
      
        
        
        <div class="col">
          <a href="/posts/linux-userfaultfd/" class="card post-preview h-100">
            <div class="card-body">
              <!--
  Date format snippet
  See: ${JS_ROOT}/utils/locale-dateime.js
-->





<em
  class="small"
  data-ts="1600905600"
  data-df="ll"
  
>
  Sep 24, 2020
</em>

              <h4 class="pt-0 my-2" data-toc-skip>Kernel userfaultfd</h4>
              <div class="text-muted small">
                <p>
                  





                  Userfault只支持匿名页，hugetlb、共享内存；

一、软件流程

1 初始化
调用__NR_userfaultfd syscall初始化
调用syscall初始化建立匿名inode文件，并初始化file-&amp;gt;private_data,并返回用户态文件fd。


  
    用户态：

    uffd = syscall(__NR_userfaultfd, O_CLOEXE...
                </p>
              </div>
            </div>
          </a>
        </div>
      
    </div>
    <!-- .card-deck -->
  </div>
  <!-- #related-posts -->


      
        
        <!-- Navigation buttons at the bottom of the post. -->

<div class="post-navigation d-flex justify-content-between">
  
    <a
      href="/posts/Peripherals-Bus-Delivery/"
      class="btn btn-outline-primary"
      prompt="Older"
    >
      <p>Peripherals Bus Delivery</p>
    </a>
  

  
    <a
      href="/posts/kernel-hmm/"
      class="btn btn-outline-primary"
      prompt="Newer"
    >
      <p>Linux Heterogeneous memory management (HMM)</p>
    </a>
  
</div>

      
        
        <!--  The comments switcher -->


      
    </div>
  </div>


        <!-- The Search results -->

<div id="search-result-wrapper" class="d-flex justify-content-center unloaded">
  <div class="col-11 post-content">
    <div id="search-hints">
      <!-- The trending tags list -->















  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
      
        
        

  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
      
        
        

  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
      
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        

  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
    
  
    
    
    
    
      
        
        



  <div id="access-tags">
    <div class="panel-heading">Trending Tags</div>
    <div class="d-flex flex-wrap mt-3 mb-1 me-3">
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/lock/">lock</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/libumem/">libumem</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/mm/">mm</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/autonuma/">autonuma</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/bfs/">BFS</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/bus/">Bus</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/caladan/">caladan</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/damon/">damon</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/deep-learning/">Deep Learning</a>
      
        
        <a class="post-tag btn btn-outline-primary" href="/tags/dma/">DMA</a>
      
    </div>
  </div>


    </div>
    <div id="search-results" class="d-flex flex-wrap justify-content-center text-muted mt-3"></div>
  </div>
</div>

      </div>
    </div>

    <!-- The Footer -->

<footer>
  <div class="container px-lg-4">
    <div class="d-flex justify-content-center align-items-center text-muted mx-md-3">
      <p>Using the <a href="https://jekyllrb.com" target="_blank" rel="noopener">Jekyll</a> theme <a href="https://github.com/cotes2020/jekyll-theme-chirpy" target="_blank" rel="noopener">Chirpy</a>
      </p>

      <p>©
        2023
        <a href="https://gitee.com/luochenglcs">luochunsheng</a>.
        
          <span
            data-bs-toggle="tooltip"
            data-bs-placement="top"
            title="Except where otherwise noted, the blog posts on this site are licensed under the Creative Commons Attribution 4.0 International (CC BY 4.0) License by the author."
          >Some rights reserved.</span>
        
      </p>
    </div>
  </div>
</footer>


    <div id="mask"></div>

    <button id="back-to-top" aria-label="back-to-top" class="btn btn-lg btn-box-shadow">
      <i class="fas fa-angle-up"></i>
    </button>

    
      <div
        id="notification"
        class="toast"
        role="alert"
        aria-live="assertive"
        aria-atomic="true"
        data-bs-animation="true"
        data-bs-autohide="false"
      >
        <div class="toast-header">
          <button
            type="button"
            class="btn-close ms-auto"
            data-bs-dismiss="toast"
            aria-label="Close"
          ></button>
        </div>
        <div class="toast-body text-center pt-0">
          <p class="px-2 mb-3">A new version of content is available.</p>
          <button type="button" class="btn btn-primary" aria-label="Update">
            Update
          </button>
        </div>
      </div>
    

    <!-- JS selector for site. -->

<!-- commons -->



<!-- layout specified -->


  

  
    <!-- image lazy-loading & popup & clipboard -->
    
  















  
    

    

  

  
    

    

  

  
    

    

  

  
    

    

  

  
    

    

  

  
    

    

  

  
    

    

  

  
    

    

  

  
    

    

  

  
    

    

  

  
    

    

  



  <script src="https://cdn.jsdelivr.net/combine/npm/jquery@3.7.0/dist/jquery.min.js,npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js,npm/simple-jekyll-search@1.10.0/dest/simple-jekyll-search.min.js,npm/lazysizes@5.3.2/lazysizes.min.js,npm/magnific-popup@1.1.0/dist/jquery.magnific-popup.min.js,npm/clipboard@2.0.11/dist/clipboard.min.js,npm/dayjs@1.11.7/dayjs.min.js,npm/dayjs@1.11.7/locale/en.min.js,npm/dayjs@1.11.7/plugin/relativeTime.min.js,npm/dayjs@1.11.7/plugin/localizedFormat.min.js,npm/tocbot@4.21.0/dist/tocbot.min.js"></script>






<script defer src="/assets/js/dist/post.min.js"></script>






    

    <!--
  Jekyll Simple Search loader
  See: <https://github.com/christian-fei/Simple-Jekyll-Search>
-->





<script>
  /* Note: dependent library will be loaded in `js-selector.html` */
  SimpleJekyllSearch({
    searchInput: document.getElementById('search-input'),
    resultsContainer: document.getElementById('search-results'),
    json: '/assets/js/data/search.json',
    searchResultTemplate: '<div class="px-1 px-sm-2 px-lg-4 px-xl-0">  <a href="{url}">{title}</a>  <div class="post-meta d-flex flex-column flex-sm-row text-muted mt-1 mb-1">    {categories}    {tags}  </div>  <p>{snippet}</p></div>',
    noResultsText: '<p class="mt-5"></p>',
    templateMiddleware: function(prop, value, template) {
      if (prop === 'categories') {
        if (value === '') {
          return `${value}`;
        } else {
          return `<div class="me-sm-4"><i class="far fa-folder fa-fw"></i>${value}</div>`;
        }
      }

      if (prop === 'tags') {
        if (value === '') {
          return `${value}`;
        } else {
          return `<div><i class="fa fa-tag fa-fw"></i>${value}</div>`;
        }
      }
    }
  });
</script>

  </body>
</html>

